﻿using System;
using System.Collections.Generic;
using System.IO;

namespace DotNetNeural.Perceptron
{
    internal class PerceptronSerializer
    {
        public void SaveToStream(Stream s, IList<float[,]> matrices)
        {
            var itemsCount = BitConverter.GetBytes(matrices.Count);
            s.Write(itemsCount, 0, itemsCount.Length);

            foreach (var m in matrices)
            {
                int dim1 = m.GetLength(0);
                int dim2 = m.GetLength(1);

                var dim1B = BitConverter.GetBytes(dim1);
                var dim2B = BitConverter.GetBytes(dim2);

                s.Write(dim1B, 0, dim1B.Length);
                s.Write(dim2B, 0, dim2B.Length);

                for (int i = 0; i < dim1; ++i)
                {
                    for (int j = 0; j < dim2; ++j)
                    {
                        var val = BitConverter.GetBytes(m[i, j]);
                        s.Write(val, 0, val.Length);
                    }
                }
            }
        }

        public IList<float[,]> LoadFromStream(Stream s)
        {
            var allBytes = new byte[s.Length];
            s.Read(allBytes, 0, allBytes.Length);
            int offset = 0;
            int itemsCount = BitConverter.ToInt32(allBytes, offset);

            offset += sizeof(Int32);

            List<float[,]> result = new List<float[,]>(itemsCount);

            for (int k = 0; k < itemsCount; ++k)
            {
                int dim1 = -1,
                    dim2 = -1;

                dim1 = BitConverter.ToInt32(allBytes, offset);
                offset += sizeof(Int32);
                dim2 = BitConverter.ToInt32(allBytes, offset);
                offset += sizeof(Int32);

                float[,] m = new float[dim1, dim2];

                for (int i = 0; i < dim1; ++i)
                {
                    for (int j = 0; j < dim2; ++j)
                    {
                        m[i, j] = BitConverter.ToSingle(allBytes, offset);
                        offset += sizeof(Single);
                    }
                }

                result.Add(m);
            }

            return result;
        }
    }
}
